package com.example.cato_restclient.restClient;

import com.example.cato_entity.entity.Ingredient;
import com.example.cato_entity.entity.Taco;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.hateoas.CollectionModel;
import org.springframework.hateoas.client.Traverson;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

import java.net.URI;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

@Service
@Slf4j
public class TacoCloud {

    @Autowired
    private RestTemplate rest;

    @Autowired
    private Traverson traverson;


    public Ingredient getIngredientById(String ingredientId) {
        return rest.getForObject("http://localhost:8080/ingredients/{id}", Ingredient.class, ingredientId);//第二个参数绑定响应的类型
    }


    public Ingredient getIngredientById_(String ingredientId) {
        Map<String, String> urlVariables = new HashMap<>();
        urlVariables.put("id", ingredientId);
        return rest.getForObject("http://localhost:8080/ingredients/{id}", Ingredient.class, urlVariables);
        //  ingredientId的值会被映射到名为id的key上
    }


    public Ingredient getIngredientById__(String ingredientId) {
        Map<String, String> urlVariables = new HashMap<>();
        urlVariables.put("id", ingredientId);
        URI uri = UriComponentsBuilder
                .fromHttpUrl("http:localhost:8080/ingredients/{id}")
                .build(urlVariables);
        return rest.getForObject(uri, Ingredient.class);
    }


    public Ingredient getIngredientById___(String ingredientId) {
        ResponseEntity<Ingredient> responseEntity = rest.getForEntity("http://localhost:8080/ingredients/{id}",
                Ingredient.class, ingredientId);
        log.info("Fetched time:" + responseEntity.getHeaders().getDate());
        return responseEntity.getBody();
        // getForEntity返回一个包裹领域对象的ResponseEntity对象。可以看响应头信息 ，而不是响应载荷领域的对象
    }


    public void updateIngredient(Ingredient ingredient) {
        rest.put("http://localhost:8080/ingredients/{id}", ingredient, ingredient.getId());
        //put方法会接受一个Object，他会被序列化并发送给指定的URL
    }

    public void deleteIngredient(Ingredient ingredient) {
        rest.delete("http://localhost:8080/ingredients/{id}", ingredient.getId());
    }


    public Ingredient createIngredient(Ingredient ingredient) {
        return rest.postForObject("http://localhost:8080/ingredients", ingredient, Ingredient.class);
    }

    public URI createIngredient_(Ingredient ingredient) {
        return rest.postForLocation("http://loaclhost:8080/ingredients", ingredient);
    }

    public Ingredient createIngredient__(Ingredient ingredient) {
        ResponseEntity<Ingredient> responseEntity = rest.postForEntity("http://localhost:8080/ingredients", ingredient, Ingredient.class);
        log.info("New resource created at" + responseEntity.getHeaders().getLocation());
        return responseEntity.getBody();
    }


    public Iterable<Ingredient> getRecentIngredientWithTraverson() {
        ParameterizedTypeReference<CollectionModel<Ingredient>> ingredientType = new
                ParameterizedTypeReference<CollectionModel<Ingredient>>() {
                };//处理泛型的
        CollectionModel<Ingredient> ingredientRes = traverson.
                follow("ingredient")     //follow导航至链接关系名为ingredients的资源
                .toObject(ingredientType);       // toObject提取资源内容，数据读到那种对象中
        Collection<Ingredient> ingredients = ingredientRes.getContent();
        return ingredients;
    }


    public Iterable<Taco> getRecentTacosWithTraverson() {
        ParameterizedTypeReference<CollectionModel<Taco>> tacoType = new
                ParameterizedTypeReference<CollectionModel<Taco>>() {
                };
        CollectionModel<Taco> tacoRes = traverson
                .follow("recents")
                .toObject(tacoType);
        Collection<Taco> tacos = tacoRes.getContent();
        return tacos;
    }


    private Ingredient addIngredient(Ingredient ingredient) {
        String ingredientsUrl = traverson
                .follow("ingredients")
                .asLink()   //得到链接本身
                .getHref();  //基于得到的链接得到链接的URL

        return rest.postForObject(ingredientsUrl, ingredient, Ingredient.class);
    }
}
